package com.young.common.query;

import javax.annotation.Nonnull;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @description：
 * @author: yangyahui01
 * @date: 11/28/24 4:28 PM
 */
public class Pagination<T> implements Serializable {
    @Nonnull
    protected final Query query;
    protected Map<String, Object> reference;
    protected int amount = -1;
    private int totalPage = -1;
    private int nextPage = -1;
    private int previousPage = -1;
    private int currentPage = -1;
    protected Collection<T> result;
    private transient boolean completed = false;

    protected Pagination(Query query) {
        this.query = query;
    }

    public int getNextPage() {
        return this.nextPage;
    }

    public int getPreviousPage() {
        return this.previousPage;
    }

    public int getCurrentPage() {
        return this.currentPage;
    }

    public boolean hasNext() {
        if (this.query.pageable()) {
            return this.currentPage < this.totalPage;
        } else {
            return false;
        }
    }

    protected void complete() {
        if (!this.completed) {
            if (this.query.pageable()) {
                this.currentPage = this.query.getPage();
                int r = this.amount % this.query.getPageSize();
                if (r == 0) {
                    this.totalPage = this.amount / this.query.getPageSize();
                } else {
                    this.totalPage = 1 + this.amount / this.query.getPageSize();
                }

                this.previousPage = this.currentPage > 1 ? this.currentPage - 1 : 1;
                this.nextPage = this.currentPage >= this.totalPage ? this.totalPage : this.currentPage + 1;
            }

            this.completed = true;
        }
    }

    public Map<String, Object> render() {
        if (!this.completed) {
            this.complete();
        }

        Map<String, Object> parameters = new HashMap();
        if (this.query.pageable()) {
            parameters.put("currentPage", this.currentPage);
            parameters.put("nextPage", this.nextPage);
            parameters.put("previousPage", this.previousPage);
            parameters.put("amount", this.amount);
            parameters.put("totalPage", this.totalPage);
        }

        parameters.put("result", this.result);
        parameters.put("query", this.query.render());
        if (this.reference != null) {
            parameters.put("reference", this.reference);
        }

        return parameters;
    }

    public Query getQuery() {
        return this.query;
    }

    public int getAmount() {
        return this.amount;
    }

    public int getTotalPage() {
        return this.totalPage;
    }

    public Collection<T> getResult() {
        return this.result;
    }
}